#include "app_pool.h"
#include <stdlib.h>
#include "../thirdparty/log.h"

#define TASK_MQUEUE_NAME "/task_mqueue"
#define PTHREAD_POOL_SIZE 10
static mqd_t mqd;
static pthread_t* pthread_pool;

/*线程任务逻辑*/
static void* pthread_func(void* args)
{
    
    while (1)
    {
        Task_handle task;
        int res = mq_receive(mqd,(char*)&task,sizeof(Task_handle),0);
        if (res != -1 && task.task_func != NULL)
        {
            task.task_func(task.args);
        }
    }
    return NULL;
}

/**
 * @brief 初始化线程池
 * 
 * @return int 0代表成功  -1代表失败
 */
int App_pool_Init(void)
{
    /*1.创建任务队列*/
    /*1.1设置生成队列的参数*/
    struct mq_attr attr; 
    attr.mq_maxmsg = 10; //队列承载消息的容量
    attr.mq_msgsize = sizeof(Task_handle); //每条消息的容量
    mqd = mq_open(TASK_MQUEUE_NAME,O_RDWR|O_CREAT,0666,&attr);
    if (mqd == -1)
    {
        perror("creat task mqueue fail...\n");
        return -1;
    }
    /*2.创建线程池*/
    pthread_pool = (pthread_t*)malloc(sizeof(pthread_t) * PTHREAD_POOL_SIZE);
    if (pthread_pool == NULL)
    {
        log_error("malloc error");
        return 1;
    }
    for (int i = 0; i < PTHREAD_POOL_SIZE; i++)
    {
        pthread_create(&pthread_pool[i],NULL,pthread_func,NULL);
    }
    return 0;
}

/**
 * @brief 向线程池提交任务
 * 
 * @param taskfunc 任务函数
 * @param args 传递的参数
 * @return int 0代表成功 -1代表失败
 */
int App_pool_Submit_Task(func taskfunc, void *args)
{
    /*创建任务结构体*/
    Task_handle task;
    task.task_func = taskfunc;
    task.args = args;
    /*向队列内发送任务*/
    int res = mq_send(mqd,(char*)&task,sizeof(Task_handle),0);
    /*结果判断*/
    if (res == -1)
    {
        perror("Submit Task to pool fail\n");
        return -1;
    }
    else
    {
        log_info("Submit Task to pool Success...\n");
    }
    return 0;
}

/**
 * @brief 摧毁线程池
 *  cancle所有线程
 * 关闭队列
 * 销毁队列
 */
void App_pool_destroy(void)
{
    /*循环cancle各个线程*/
    for (int i = 0; i < PTHREAD_POOL_SIZE; i++)
    {
        pthread_cancel(pthread_pool[i]);
    }
    /*释放内存*/
    free(pthread_pool);
    /*关闭队列*/
    mq_close(mqd);
    /*删除队列*/
    mq_unlink(TASK_MQUEUE_NAME);
}
